
#include "camera.h"
#include "vector3.h"

#include "v3d_interface.h"


Camera::Camera()
{
	mCameraType = LANDOBJECT;
	Initialize();
}

Camera::Camera(Camera::CameraType cameraType)
{
	mCameraType = cameraType;
	Initialize();
}

void Camera::Initialize()
{
	mEyePosition.set(0.0f, 0.0f, -15.0f);
	mLook.set(0.0f, 0.0f, 10.0f);
	mUp.set(0.0f,1.0f,0.0f);
	mRight.set(1.0f,0.0f,0.0f);
	mCamMoveSpeed = 25;
	mCamRotateSpeed = 20;
}
/*
void Camera::UpdateUserInput(POINT *inPoint)
{
	mMouseCurPosition = *inPoint;
}
*/
/*
void Camera::UpdateCameraInput(bool * inKeys, float deltaTime, bool mLButtonDown)
{
	Matrix4x4 matRotation;
	int inXDiff = 0;//mMouseCurPosition.x - mMouseLastPosition.x;
	int inYDiff = 0;//mMouseCurPosition.y - mMouseLastPosition.y;

	if(mLButtonDown)
	{
		if(inYDiff != 0)
		{
			matRotation.rotate((float)inYDiff/3.0f,mRight);
			matRotation.transformVector(&mLook);
			matRotation.transformVector(&mUp);
		}

		if( inXDiff != 0 )
		{
			matRotation.rotate((float)inXDiff / 2.0f, mUp );
			matRotation.transformVector( &mLook );
			matRotation.transformVector( &mUp );
		}

		Vector3 tempLook = mLook;
		Vector3 tempRight = mRight;
	}

	if(inKeys['W'])
	{
		Walk(mCamMoveSpeed * deltaTime);
	}

	if(inKeys['S'])
	{
		Walk(-mCamMoveSpeed * deltaTime);
	}

	if(inKeys['A'])
	{
		Strafe(-mCamMoveSpeed * deltaTime);
	}

	if(inKeys['D'])
	{
		Strafe(mCamMoveSpeed * deltaTime);
	}

	if(inKeys[37])   //left arrow
	{
		RotateSide(mCamRotateSpeed * deltaTime);
	}

	if(inKeys[39])  //right arrow
	{
		RotateSide(-mCamRotateSpeed * deltaTime);
	}

	if(inKeys[38])   //up arrow
	{
		RotateUp(mCamRotateSpeed * deltaTime);
	}

	if(inKeys[40])  //down arrow
	{
		RotateUp(-mCamRotateSpeed * deltaTime);
	}
	
//	mMouseLastPosition = mMouseCurPosition;
}
*/
void Camera::UpdateCameraInput(float deltaTime)
{
	Matrix4x4 matRotation;

	if(IINTERFACE->IsKey('W'))
	{
		Walk(mCamMoveSpeed * deltaTime);
	}

	if(IINTERFACE->IsKey('S'))
	{
		Walk(-mCamMoveSpeed * deltaTime);
	}

	if(IINTERFACE->IsKey('A'))
	{
		Strafe(-mCamMoveSpeed * deltaTime);
	}

	if(IINTERFACE->IsKey('D'))
	{
		Strafe(mCamMoveSpeed * deltaTime);
	}
/*
	if(inKeys[37])   //left arrow
	{
		RotateSide(mCamRotateSpeed * deltaTime);
	}

	if(inKeys[39])  //right arrow
	{
		RotateSide(-mCamRotateSpeed * deltaTime);
	}

	if(inKeys[38])   //up arrow
	{
		RotateUp(mCamRotateSpeed * deltaTime);
	}

	if(inKeys[40])  //down arrow
	{
		RotateUp(-mCamRotateSpeed * deltaTime);
	}
*/
}


void Camera::RotateUp(float units)
{
	Matrix4x4 matRotation;
	matRotation.rotate(units,mRight);
	matRotation.transformVector(&mLook);
	matRotation.transformVector(&mUp);
}

void Camera::RotateSide(float units)
{
	Matrix4x4 matRotation;
	matRotation.rotate(units, mUp );
	matRotation.transformVector( &mLook );
	matRotation.transformVector( &mUp );
}

void Camera::Walk(float units)
{
	Vector3 tempVector;
	tempVector.set(mLook.x,0.0f,mLook.z);
	if( mCameraType == LANDOBJECT )
		mEyePosition += tempVector * units;

	if( mCameraType == AIRCRAFT )
		mEyePosition += mLook * units;
}
void Camera::Strafe(float units)
{
	Vector3 tempVector;
	tempVector.set(mRight.x, 0.0f, mRight.z);
		// move only on xz plane for land object
	if( mCameraType == LANDOBJECT )
		mEyePosition +=  tempVector * units;

	if( mCameraType == AIRCRAFT )
		mEyePosition += mRight * units;
}

void Camera::Fly(float units)
{
	// move only on y-axis for land object
	if( mCameraType == LANDOBJECT )
		mEyePosition.y += units;

	if( mCameraType == AIRCRAFT )
		mEyePosition += mUp * units;
}

//-----------------------------------------------------------------------------
// Name : updateViewMatrix() 
// Desc : Builds a view matrix suitable for OpenGL.
//
// Here's what the final view matrix should look like:
//
//  |  rx   ry   rz  -(r.e) |
//  |  ux   uy   uz  -(u.e) |
//  | -lx  -ly  -lz   (l.e) |
//  |   0    0    0     1   |
//
// Where r = Right vector
//       u = Up vector
//       l = Look vector
//       e = Eye position in world space
//       . = Dot-product operation
//
//-----------------------------------------------------------------------------
float *Camera::GetViewMatrix(void)
{
	view.identity();

	mLook.normalize();

	mRight = Vector3::crossProduct(mLook, mUp);
	mRight.normalize();

	mUp =  Vector3::crossProduct(mRight, mLook);
	mUp.normalize();

	view.m[0] =  mRight.x;
	view.m[1] =  mUp.x;
	view.m[2] = -mLook.x;
	view.m[3] =  0.0f;

	view.m[4] =  mRight.y;
	view.m[5] =  mUp.y;
	view.m[6] = -mLook.y;
	view.m[7] =  0.0f;

	view.m[8]  =  mRight.z;
	view.m[9]  =  mUp.z;
	view.m[10] = -mLook.z;
	view.m[11] =  0.0f;

	view.m[12] = - Vector3::dotProduct(mRight, mEyePosition);
	view.m[13] = - Vector3::dotProduct(mUp, mEyePosition);
	view.m[14] =   Vector3::dotProduct(mLook, mEyePosition);
	view.m[15] =  1.0f;

	return view.m;

}

